<?php

namespace common\modules\site;

/**
 * This is the model class for table "region".
 *
 * @property int $regionId
 * @property int $parentId 父id
 * @property string $name 简称
 * @property string $fullName 全称
 * @property string $pinyin 字母
 * @property string $code 拼音
 * @property string $location 地理位置
 * @property int $sorting 排序
 * @property int $level 等级
 */
class Region extends \xing\helper\yii\BaseActiveModel
{
    public static $cacheFindOne = true;
    public static $cacheOneTime = 86400; // 缓存时间

    /**
     * @var bool $cacheTree 缓存树数据
     */
    public static $cacheTree = true;

    /**
     * @var string $cacheTreeKey 缓存键名
     */
    public static $cacheTreeKey = 'Region:tree';

    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return 'region';
    }

    /**
     * {@inheritdoc}
     */
    public function rules()
    {
        return [
            [['parentId'], 'required'],
            [['parentId', 'level', 'sorting'], 'integer'],
            [['name', 'fullName'], 'string', 'max' => 50],
            [['pinyin', 'code'], 'string', 'max' => 500],
            [['location'], 'string', 'max' => 100],
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'regionId' => 'regionId',
            'parentId' => '父id',
            'name' => '简称',
            'fullName' => '全称',
            'pinyin' => '字母',
            'code' => '拼音',
            'location' => '地理位置',
            'level' => '等级',
        ];
    }


    /**
     * 读取所有二级和三级地区
     * @param $parentId
     * @return array|\yii\db\ActiveRecord[]
     */
    public static function readChildren($parentId)
    {
        $data = static::getOneLevel($parentId);
        if (empty($data)) return [];

        $return = [];
        $return[] = [
            'value' => '-1',
            'text' => '不限',
            'children' => [],
        ];
        foreach ($data as $k => $v) {
            $return[] = [
                'value' => $v->regionId,
                'text' => $v->name,
                'children' => static::readChildren($v->regionId),
            ];
        }
        return $return;
    }

    /**
     * 读取下一级数据
     * @param $parentId
     * @param string|array $select
     * @return $this[]|\yii\db\ActiveRecord[]
     */
    public static function getOneLevel($parentId, $select = '*')
    {
        $data = self::find()->select($select)->where(['parentId' => $parentId])->all();
        return $data;
    }

    /**
     * 读取名称
     * @param $id
     * @return string
     */
    public static function readName($id)
    {
        return static::readFieldValue('name', $id);
    }

    /**
     * 返回本级和上级行政区，共两级
     * @param $id
     * @param string $connector
     * @return string
     */
    public static function readTwoName($id, $connector = '')
    {
        if (empty($id)) return '';
        $data = self::findOne($id);
        if (empty($data->parentId)) return $data->name ?? '';
        $twoData = self::findOne($data->parentId);
        $name = $twoData->name ?? '';
        return str_replace(['省', '市', '一级行政区'] , '', ($name ? $name . $connector : '') . $data->name);
    }

    /**
     * 返回完全的城市
     * @param $id
     * @param string $connector
     * @return string
     */
    public static function readFullName($id, $connector = '')
    {
        if (empty($id)) return '';
		$fullName = [];
		while (!empty($data = self::findOne($data->parentId ?? $id))) {
			array_unshift($fullName, $data->name);
		}
        return implode($connector, $fullName);
    }


    /**
     * @param $id
     * @return mixed|string
     */
    public static function readByCode($id)
    {
        return static::readFieldValue('areaCode', $id);
    }

    /**
     * 读取上级ids
     * @param int $id 主键id
     * @param bool $isContainItself 是否包含自身
     * @return array
     */
    public static function readParentIds($id, $isContainItself = true)
    {
        $return = [];
        // 包含自身
        $isContainItself && $return[] = $id;
        $n = 0;
        do {
            $region = self::findOne(isset($region) ? $region->parentId : $id);
            if (empty($region) || $region->parentId == 0) return $return;
            array_unshift($return, $region->parentId);
        } while (!empty($region) && $region->parentId > 0 && ++$n <= 5);
        return $return;
    }

    /**
     * 读取栏目树
     * @param int $parentId
     * @param bool $bindIndex
     * @return array|\yii\db\ActiveRecord[]
     */
    public static function readCategoryTrue($parentId = 0, $bindIndex = false, $maxLevel = 3)
    {
        $m = self::find()->where(['parentId' => $parentId])->andWhere(['<=', 'level', $maxLevel])->asArray();
        if ($bindIndex) $m->indexBy('regionId');
        $data = $m->all();
        if (empty($data)) return $data;

        static $nnn;
        if (++$nnn > 10000) exit('无限循环？超1万次了');


        # 获取子栏目：如果有下级结构，则读取下级结构，否则读取属性值
        foreach ($data as $k => $v) {
            $data[$k]['data'] = static::readCategoryTrue($v['regionId']);
        }
        return $data;
    }
    /**
     * 获取所有子id
     * @param $parentId
     * @return array
     */
    public static function readChildrenIds($parentId, $maxLevel = 3, $maxNumber = 3000)
    {
        if (empty($parentId)) return null;
        $cacheKey = 'R:RCI:' . $maxLevel . ':' . ($parentId ?: 0);
        $ids = \Yii::$app->cache->get($cacheKey) ?: [];
//        $ids = [];
        if (empty($ids)) {

            $ids = [$parentId];
            $list = self::find()->select(['regionId'])->where(['parentId' => $parentId])->andWhere(['<=', 'level', $maxLevel])->all();
            if (empty($list)) return $ids;

            foreach ($list as $v) {
                $ids = array_merge($ids, static::readChildrenIds($v->regionId, $maxLevel));
                // 防止读取太多的id
                if (count($ids) > $maxNumber) return $ids;
            }
            \Yii::$app->cache->set($cacheKey, $ids, 86400 * 7);
        }
        return $ids;
    }


    /**
     * @param int $parentId
     * @param bool $showEmpty
     * @return array
     */
    public static function dropDownTrue($parentId = 0, $showEmpty = false, $maxLevel = 3)
    {
        $cacheKey = static::$cacheTreeKey . $parentId;
        if (static::$cacheTree) {
            $cache =\ Yii::$app->cache->get($cacheKey);
            if (!empty($cache)) {
                if ($showEmpty && is_string($showEmpty)) array_unshift($cache, $showEmpty);
                return $cache;
            }
        }

        $data = static::readCategoryTrue($parentId);
        $return = [];
        if ($showEmpty) $return[''] = is_string($showEmpty) ? $showEmpty : '一级行政区域';
        if (empty($data)) return $return;

        // 删除树型缓存
        $return = static::_dropDownTrue($data);
        if (static::$cacheTree) \Yii::$app->cache->set($cacheKey, $return);

        return $return;
    }

    /**
     * @param $data
     * @param string $fh
     * @return array
     */
    public static function _dropDownTrue($data, $fh = '')
    {
        static $return, $nnn;
        $fh .= '| ';
        if (empty($data)) return [];
        foreach ($data as $v) {
            $return[$v['regionId']] =  $fh. $v['name'];
            if (isset($v['data']) && !empty($v['data'])) static::_dropDownTrue($v['data'], $fh);
            $nnn ++;
        }
        /*if ($nnn >= 10000) {
            exit('循环了10000次，应该没这么多数据吧？为避免造成无限循环，终止程序了');
        }*/
        return $return;
    }
}
